#include "Level.h"
#include "Unit.h"
#include "Struct.h"
#include "RessourceStruct.h"
#include "GrassTile.h"
#include "WaterTile.h"
#include "SandTile.h"
#include "DirtTile.h"
#include "ForumStruct.h"
#include "FarmStruct.h"
#include "TreeStruct.h"

Level::Level()
{
	int u;
	int x;
	int y;
	for(u = 0; u < 2; u++)
	{
		for(y = 0; y < 64; y++)
		{
			for(x = 0; x < 64; x++)
			{
				m_tile[u][y][x] = NULL;
			}
		}
	}
}

Level::~Level()
{
	int u;
	int x;
	int y;
	for(u = 0; u < 2; u++)
	{
		for(y = 0; y < 64; y++)
		{
			for(x = 0; x < 64; x++)
			{
				delete m_tile[u][y][x];
			}
		}
	}
}

int Level::random(int a, int b)
{
    return rand()%(b-a) +a;
}

void Level::addUnit(Unit *unit, sf::Vector2f position, const int idTeam)
{
	unsigned int e = 0;
	while(e < m_unit.size())
	{
		if(m_unit[e]->getDead())
		{
			m_unit[e] = unit;
			return;
		}
		e++;
	}
	m_unit.push_back(unit);
	while(getTile(position, 0) == 1)
	{
		position.x = (float)random(0, m_width);
		position.y = (float)random(0, m_height);
	}
	m_unit[e]->init(idTeam, position, m_imageManager);
}

bool Level::addStruct(Struct *structure, sf::Vector2f position, const int idTeam)
{
	unsigned int e = 0;
	if(getTile(position, 0) == 1)
		return false;
	while(e < m_struct.size())
	{
		if(m_struct[e]->isDestroy())
		{
			m_struct[e] = structure;
			m_struct[e]->init(position, idTeam, m_imageManager);
			return true;
		}
		e++;
	}
	m_struct.push_back(structure);
	m_struct[e]->init(position, idTeam, m_imageManager);
	return true;
}

bool Level::addRessourceStruct(RessourceStruct *ressourceStruct, sf::Vector2f position)
{
	if(getTile(position, 0) == 1)
		return false;
	if(position.x < 0)
		position.x = 0;
	if(position.y < 0)
		position.y = 0;
	unsigned int e = 0;
	while(e < m_ressourceStruct.size())
	{
		if(m_ressourceStruct[e]->isDestroy())
		{
			m_ressourceStruct[e] = ressourceStruct;
			m_ressourceStruct[e]->init(position, m_imageManager);
			return true;
		}
		e++;
	}
	m_ressourceStruct.push_back(ressourceStruct);
	m_ressourceStruct[e]->init(position, m_imageManager);
	return true;
}

void Level::loadLevel(const std::string chemin)
{
	sf::Image imageLevel;
	imageLevel.loadFromFile(chemin);
	m_width = imageLevel.getSize().x;
	m_height = imageLevel.getSize().y / 2;
	int x;
	int y;
	int u;
	float px;
	float py;
	for(u = 0; u < 2; u++)
	{
		px = 0;
		py = 0;
		for(y = 0; y < m_height; y++)
		{
			for(x = 0; x < m_width; x++)
			{
				if(imageLevel.getPixel(x, y + m_height * u + (1 * u)) == sf::Color::Color(38, 127, 0))
				{
					m_tile[u][y][x] = new GrassTile();
					m_tile[u][y][x]->init(sf::Vector2f(px, py), m_imageManager);
				}
				else if(imageLevel.getPixel(x, y + m_height * u + (1 * u)) == sf::Color::Color(0, 74, 127))
				{
					m_tile[u][y][x] = new WaterTile();
					m_tile[u][y][x]->init(sf::Vector2f(px, py), m_imageManager);
				}
				else if(imageLevel.getPixel(x, y + m_height * u + (1 * u)) == sf::Color::Color(204, 170, 0))
				{
					m_tile[u][y][x] = new SandTile();
					m_tile[u][y][x]->init(sf::Vector2f(px, py), m_imageManager);
				}
				else if(imageLevel.getPixel(x, y + m_height * u + (1 * u)) == sf::Color::Color(127, 51, 0))
				{
					m_tile[u][y][x] = new DirtTile();
					m_tile[u][y][x]->init(sf::Vector2f(px, py), m_imageManager);
				}
				else if(imageLevel.getPixel(x, y + m_height * u + (1 * u)) == sf::Color::Color(128, 128, 128))
				{
					addStruct(new ForumStruct(), sf::Vector2f(px, py), 1);
				}
				else if(imageLevel.getPixel(x, y + m_height * u + (1 * u)) == sf::Color::Color(127, 106, 0))
				{
					addStruct(new FarmStruct(), sf::Vector2f(px, py), 1);
				}
				else if(imageLevel.getPixel(x, y + m_height * u + (1 * u)) == sf::Color::Color(29, 96, 0))
				{
					addRessourceStruct(new TreeStruct(), sf::Vector2f(px, py));
				}
				px += 16;
			}
			py += 16;
			px = 0;
		}
	}
	m_width = imageLevel.getSize().x * 16 - 1;
	m_height = (imageLevel.getSize().y - 1) / 2 * 16 - 1;
}

bool Level::collisionTile(const sf::Vector2f position, const int direction)
{
	if(direction == 1)
	{
		int posX = (int)(position.x + 8) / 16;
		int posY = ((int)position.y / 16) + 1;
		if(posX < 0)
			posX = 0;
		if(posY < 0)
			posY = 0;
		if(m_tile[0][posY][posX] != NULL && m_tile[0][posY][posX]->isBlocking())
			return true;
		if(position.y + 16 > m_height)
		return true;
	}	
	if(direction == 2)
	{
		int posX = (int)(position.x + 8) / 16;
		int posY = ((int)(position.y + 16) / 16) - 1;
		if(posX < 0)
			posX = 0;
		if(posY < 0)
			posY = 0;
		if(m_tile[0][posY][posX] != NULL && m_tile[0][posY][posX]->isBlocking())
			return true;
		if(position.y < 0)
		return true;
	}
	if(direction == 3)
	{
		int posX = ((int)position.x / 16) + 1;
		int posY = (int)(position.y + 8) / 16;
		if(posX < 0)
			posX = 0;
		if(posY < 0)
			posY = 0;
		if(m_tile[0][posY][posX] != NULL && m_tile[0][posY][posX]->isBlocking())
			return true;
		if(position.x + 16 > m_width)
		return true;
	}
	if(direction == 4)
	{
		int posX = ((int)(position.x + 16) / 16) - 1;
		int posY = (int)(position.y + 8) / 16;
		if(posX < 0)
			posX = 0;
		if(posY < 0)
			posY = 0;
		if(m_tile[0][posY][posX] != NULL && m_tile[0][posY][posX]->isBlocking())
			return true;	
		if(position.x < 0)
		return true;
	}
	return false;
}

void Level::tri()
{
	int x, y, u, place;
	place = 0;
	std::vector<Unit*> unit;
	unit.resize(m_unit.size());

	for(y = 0; y < unit.size(); y++)
	{
		unit[y] = NULL;
	}

	for(x = 0; x < m_unit.size(); x++)
	{
		for(y = 0; y < unit.size(); y++)
		{
			if(unit[y] != NULL)
			{
				if(m_unit[x]->getPosition().y < unit[y]->getPosition().y)
				{
					for(u = y + 1; u >= y; u--)
					{
						unit[u] = unit[u-1];
						std::cout << y << " ";
						std::cout << u << " >> " << u-1 << std::endl;
						place++;
						y = unit.size();
					}
				}
			}
			else
			{
				unit[y] = m_unit[x];
				place++;
				y = unit.size();
			}
		}
	}
	std::cout << place << std::endl;
}

int Level::getTile(const sf::Vector2f position, const int u) const
{
	int x = (int)position.x / 16;
	int y = (int)position.y / 16;
	if(x < 0)
		x = 0;
	if(y < 0)
		y = 0;
	if(x > m_width / 16)
		x = m_width / 16;
	if(y > m_height / 16)
		y = m_height / 16;
	return m_tile[u][y][x]->m_id;
}

void Level::setTile(Tile *tile, const sf::Vector2f position, const int u)
{
	int x = (int)position.x / 16;
	int y = (int)position.y / 16;
	m_tile[u][y][x] = tile;
	m_tile[u][y][x]->init(position, m_imageManager);
}

std::vector<Unit*>* Level::getUnit()
{
	return &m_unit;
}

std::vector<Struct*>* Level::getStruct()
{
	return &m_struct;
}

std::vector<RessourceStruct*>* Level::getRessourceStruct()
{
	return &m_ressourceStruct;
}

void Level::init(ImgMgr *imageManager)
{
	int u;
	int x;
	int y;
	m_width = 0;
	m_height = 0;
	m_imageManager = imageManager;
	for(u = 0; u < 2; u++)
	{
		for(y = 0; y < 64; y++)
		{
			for(x = 0; x < 64; x++)
			{
				m_tile[u][y][x] = NULL;
			}
		}
	}
}

void Level::maj(RessourceMgr *ressourceMgr)
{
	int u;
	int x;
	int y;
	unsigned int e = 0;
	for(u = 0; u < 2; u++)
	{
		for(y = 0; y < 64; y++)
		{
			for(x = 0; x < 64; x++)
			{
				if(m_tile[u][y][x] != NULL)
					m_tile[u][y][x]->maj(this);
			}
		}
	}
	while(e < m_unit.size())
	{
		if(!m_unit[e]->getDead())
			m_unit[e]->maj(this);
		e++;
	}
	e = 0;
	while(e < m_struct.size())
	{
		if(!m_struct[e]->isDestroy())
			m_struct[e]->maj(this, ressourceMgr);
		e++;
	}
	e = 0;
	while(e < m_ressourceStruct.size())
	{
		if(!m_ressourceStruct[e]->isDestroy())
			m_ressourceStruct[e]->maj(this);
		e++;
	}
}

void Level::render(sf::RenderWindow *app, sf::View *view)
{
	int x, y, u;
	unsigned e = 0;
	int xView = (int)view->getCenter().x / 16;
	int yView = (int)view->getCenter().y / 16;
	for(u = 0; u < 2; u++)
	{
		for(y = yView - 12; y < yView + 13; y++)
		{
			if(y < 0)
				y = 0;
			for(x = xView - 17; x < xView + 17; x++)
			{
				if (x < 0)
					x = 0;
				if(m_tile[u][y][x] != NULL)
					m_tile[u][y][x]->render(app);
			}
		}
	}
	e = 0;
	while(e < m_unit.size())
	{
		m_unit[e]->render(app);
		e++;
	}
	e = 0;
	while(e < m_ressourceStruct.size())
	{
		m_ressourceStruct[e]->render(app);
		e++;
	}
	e = 0;
	while(e < m_struct.size())
	{
		m_struct[e]->render(app);
		e++;
	}
}

